package org.goobs.internet;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

import org.goobs.internet.Browser.BrowserException;

public class WikipediaPage {

	private static final int STARTS = 1;
	private static final int ENDS = 2;
	private static final int CONTAINS = 3;
	
	private static class WikiException extends RuntimeException{
		/**
		 * 
		 */
		private static final long serialVersionUID = -4554916790886176321L;
		private WikiException(){
			super();
		}
		private WikiException(String msg){
			super(msg);
		}
	}
	
	
	private String name;
	
	public WikipediaPage(String name){
		this.name = name;
	}
	
	
	private boolean isPunctuation(char c){
		return !(   (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9')   );
	}
	
	private String phraseProcess(String input){
		input = input.replaceAll("i\\.e\\.", "ie");
		input = input.replaceAll("e\\.g\\.", "eg");
		return input;
	}
	
	private String processPunctuation(String input){
		StringBuilder b = new StringBuilder();
		char[] chars = input.toCharArray();
		for(int i=0; i<chars.length-1; i++){
			if(isPunctuation(chars[i])){
				b.append(' ').append(chars[i]).append(' ');
			}else{
				b.append(chars[i]);
			}
		}
		b.append(chars[chars.length-1]);
		return b.toString();
	}
		
	private boolean isSentenceEnd(String word){
		if(word==null){
			return false;
		}
		//(is the word a period?)
		if(word.length() == 1){
			if(word.charAt(0) == '.'){
				return true;
			}else{
				return false;
			}
		}
		//(does the word end with a period?)
		if(word.charAt(word.length()-1) == '.'){
			if(!word.substring(0, word.length()-1).contains(".")){
				return true;
			}else{
				return false;
			}
		}
		//(does the word end with a quote?)
		if(word.charAt(word.length()-1) == '\"' ||
				word.charAt(word.length()-1) == '\'' ){
			if(word.charAt(word.length()-2) == '.'){
				return true;
			}else{
				return false;
			}
		}
		//(word is nothing special)
		return false;
	}
	
	private void bleedUntil(char end, String term, int cond, StringTokenizer tokens){
		while(term != null){
			switch(cond){
			case STARTS:
				if(term.charAt(0) == end){
					return;
				}
				break;
			case ENDS:
				if(term.charAt(term.length()-1) == end){
					return;
				}
				break;
			case CONTAINS:
				if(term.contains("" + end)){
					return;
				}
				break;
			default:
				throw new WikiException("Invalid condition for bleedUntil(): " + cond);	
			}
			if(tokens.hasMoreTokens()){
				term = tokens.nextToken();
			}else{
				term = null;
			}
		}
	}
	
	private void extract(String para, List <String> sentences){
		//--Clean string
		para = phraseProcess(para);
		para = processPunctuation(para);
		//--Extract string
		StringBuilder b = new StringBuilder();
		StringTokenizer tokens = new StringTokenizer(para);
		boolean inQuote = false;
		String token=null, lastToken=null;
		while(tokens.hasMoreTokens()){
			lastToken = token;
			token = tokens.nextToken();
			//(bleed undesirable parts)
			if(token.charAt(0) == '('){
				bleedUntil(')', token, ENDS, tokens);
				continue;
			}
			if(token.charAt(0) == '['){
				bleedUntil(']', token, ENDS, tokens);
				continue;
			}
			//(manage quotes)
			if(token.equals("\"")){
				inQuote = !inQuote;
			}
			//(build sentence)
			b.append(token).append(" ");
			if(!inQuote && (isSentenceEnd(token) || isSentenceEnd(lastToken))){
				String sent = b.toString().trim();
				if(sent.length() > 1){
					sentences.add(sent);
				}
				b = new StringBuilder();
				token=null;
				lastToken=null;
			}
		}
	}
	
	public String[] extractSentences() throws WikiException{
		log("EXTRACTING: " + name);
		String url = "http://wikipedia.org/wiki/" + (name.replaceAll(" ", "_"));
		log("   url: " + url);
		//--Get page
		Browser page = new Browser();
		try {
			page.pointTo(url);
		} catch (BrowserException e) {
			throw new WikiException("Could not load page for " + name + ": " + e.getMessage());
		}
		log("   page loaded");
		
		//--Get paragraphs
		List <String> paragraphs = new LinkedList <String> ();
		Iterator <String> iter = page.findHtmlBetween("<p>", "</p>", false);
		while(iter.hasNext()){
			String text = Browser.extractText(iter.next());
			paragraphs.add(text);
		}
		log("   paragraphs extracted");
		
		//--Get sentences
		List <String> sentences = new LinkedList <String> ();
		for(String par : paragraphs){
			extract(par, sentences);
		}
		log("   sentences extracted");
		
		String[] rtn = new String[sentences.size()];
		rtn = sentences.toArray(rtn);
		return rtn;
	}
	
	
	
	
	private static void log(String msg){
		System.out.println(msg);
	}
	
	public static void main(String[] args){
		WikipediaPage page = new WikipediaPage("greeks");
		String[] sent = page.extractSentences();
		
		for(String s : sent){
			System.out.println(s);
		}
	}
}
